package com.woniuxueyuan.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.nimbusds.jose.JOSEException;
import com.woniuxueyuan.entity.Address;
import com.woniuxueyuan.entity.Book;
import com.woniuxueyuan.entity.User;
import com.woniuxueyuan.entity.UserCart;
import com.woniuxueyuan.entity.dto.*;
import com.woniuxueyuan.mapper.UserMapper;
import com.woniuxueyuan.service.UserService;
import com.woniuxueyuan.util.JWTUtil;
import com.woniuxueyuan.util.ResponseData;
import com.woniuxueyuan.util.UserContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    //专门操作redis工具栏（新增，删除，查看）
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedisTemplate redisTemplateInit; //默认 泛型RedisTemplate<object,object>
    /**
     * 用户登录接口
     * 1：根据用户名查询用户信息
     * 2：对比数据库的密码和前端输入密码
     * 3给该用户生成jwt
     * 4.把jwt'存入redis中
     *
     * @param user
     * @return
     */

    @Override
    public LoginDTO login(User user) throws JOSEException {
        //1：根据用户名查询用户信息
        User userInfo = userMapper.queryUserByAcoount(user.getAccount());
        if(userInfo==null){
            return null;
        }
        //2对比数据库的密码和前端输入密码
        //为了密码安全性，不会直接用原生的密码加密后放入数据库。给密码加上盐值后放入数据库
        String md5PWD = SecureUtil.md5(user.getPassword()+"1a2b3c4d");
        if(!userInfo.getPassword().equals(md5PWD)){
            return null;
        }
//        3给该用户生成jwt
        HashMap<String, Object> userMap = new HashMap<>();
        //不能放敏感信息
        userMap.put("id",userInfo.getId());
        userMap.put("account",userInfo.getAccount());
        String jwt = JWTUtil.createJWT(userMap);
        //4.把jwt'存入redis中  redis:采用key-vaule方式存储的数据库，mysql是关系数据库，表格
        //参数3：数值，参数4：时间单位（秒，毫秒，分钟）
        stringRedisTemplate.opsForValue().set("JWT:"+userInfo.getId(),jwt,15, TimeUnit.DAYS);

        //6把用户信息和jwt一起返回
//        Map resultMap = new HashMap();
//        resultMap.put("userInfo",new UserDTO(userInfo));//把po改成DTO
//        resultMap.put("jwt",jwt);
        return new LoginDTO(jwt,new UserDTO(userInfo));
    }

    /**
     * 用户添加购物车
     * 1；判断用户是否添加此书籍
     * 没有：新增
     * 有 ：修改
     * @param id
     * @param buyNum
     * @return
     */

    @Override
    public void addCart(Integer id, Integer buyNum) throws ParseException {
        //怎么获取用户id
        Integer userId = UserContext.getUserId();
        UserCart userCart = userMapper.queryUserCart(userId,id);

        UserCart userCartInfo = new UserCart();
        userCartInfo.setBookId(id);
        //考虑新增还是修改
        userCartInfo.setBuyNum(userCart==null?buyNum:buyNum+userCart.getBuyNum());
        //获取redis缓存的该书籍信息（获取最新单价）
       Book cacheBook= (Book) redisTemplateInit.opsForHash().get("BOOKSERVICEIMPL:QUERYBYID", id + "");
        userCartInfo.setBuyPrice(cacheBook.getPrice());//最新单价
        userCartInfo.setUserId(userId);
        userCartInfo.setTotalPrice(cacheBook.getPrice().multiply(new BigDecimal(userCartInfo.getBuyNum())));

        if(userCart==null){
            //新增userCartInfo
            userMapper.addUserCart(userCartInfo);
        }else {
            //修改userCartInfo
            userCartInfo.setId(userCart.getId());
            userMapper.updateUserCart(userCartInfo);
        }
    }

    /**
     * 查询地址和购物车信息
     * @return
     */
    @Override
    public Map queryAddrAndUserCart() throws ParseException {
        Integer userId = UserContext.getUserId();
        List<Address> addresses = userMapper.queryUserAddr(userId);
        List<UserCart> userCarts = userMapper.queryUserShoppingCart(userId);
        Map map=new HashMap();
        map.put("addresses",addresses);
        map.put("userCarts",userCarts);
        return map;

    }
}
